package sample;

import com.sun.org.apache.bcel.internal.generic.ANEWARRAY;
import javafx.animation.FadeTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.media.AudioTrack;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.Track;
import javafx.scene.paint.*;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;

enum ButtonEnum{

    PAUSE("pause"),
    NEXT("next"),
    PRE("pre"),
    PLAY("play");

    String name;
    ButtonEnum(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

public class MusicPlayer extends Application {
    private Duration currentSecond ;
    private boolean mouse = false;
    private int index = 0;
    private MediaPlayer mediaPlayer;
    private Slider process = new Slider();
    private Rectangle processRectangle = new Rectangle();
    Slider slider = new Slider(0,1,0.2);
    private String buttonName ="";
    private AnchorPane spectrum_Pane;
    private AnchorPane anchorPane = new AnchorPane();
    private double width_stage;
    private Rectangle rectangle = new Rectangle();
    private List<String> songNameList ;
    private static String path ="/";
    private boolean isClicked;
    private ListView<Text> listView;
    private static String documentBase;
    private Button next_bu;
    private Map<Integer,String> songWordsMap;
    private Text wordText;
    //    private Duration currentPlayTime;
    @Override
    public void start(Stage primaryStage) throws Exception {

        List<Media> list = new ArrayList<>();

        Button play_bu = new Button("播放");
        Button pause_bu = new Button(" 暂停");
        Button pre_bu = new Button(" <<上一首");
        next_bu = new Button(" 下一首>>");
        Button songs = new Button("歌单");

//        Label label = new Label("音量");

//        slider.setShowTickMarks(true);
//        slider.setShowTickLabels(true);
//        slider.isShowTickMarks(true);
//        slider.setStyle("-fx-background-color: blue");
//        process.setPrefWidth(300);
//        process.setStyle("-fx-color-label-visible: true");

//        slider.setRotate(90);
        slider.setPrefWidth(100);
//        String source = "https://webfs.yun.kugou.com/202002031328/d9c8dfbb63fbb02fedc0121b68578d89/G186/M04/04/13/mpQEAF4gAKyAUuRJAEXF4e64Zz8343.mp3";

        loadMusicDir(path,list);


        HBox hBox = new HBox(50,pre_bu,play_bu,pause_bu,next_bu,slider,songs);
        hBox.setAlignment(Pos.BOTTOM_CENTER);
        AnchorPane.setBottomAnchor(slider,20.0);
        AnchorPane.setBottomAnchor(hBox,30.0);
        Image image = new Image("file:"+documentBase + "image/haizei.jpeg");
        System.out.println(MusicPlayer.class.getResource("image"));

        System.out.println(image.getHeight()+" "+image.getWidth());
       // anchorPane.setMaxSize(700,1120);

//        anchorPane.setOpacity(0.5);

//        anchorPane.setPrefSize(1120,700);
//        s.setStyle("-fx-background-image: url(\"file:/home/hankun/project/demofx/src/lesson01/libai.jpg\")");
        ImageView imageView = new ImageView(image);
        imageView.fitHeightProperty().bind(anchorPane.heightProperty());
        imageView.fitWidthProperty().bind(anchorPane.widthProperty());
        hBox.prefHeightProperty().bind(anchorPane.heightProperty());
        hBox.prefWidthProperty().bind(anchorPane.widthProperty());
        Scene scene = new Scene(anchorPane);
//        scene.heightProperty().addListener(((observable, oldValue, newValue) ->{
//            System.out.println(newValue.doubleValue());
//            anchorPane.setPrefHeight(newValue.doubleValue());
//        }));
//        scene.setFill(Paint.valueOf("black"));
        primaryStage.setOpacity(0.95);
        primaryStage.setFullScreen(false);
        primaryStage.setTitle("One Piece Music");
        primaryStage.getIcons().add(new Image("file:"+documentBase+"src/sample/music.png"));
        primaryStage.initStyle(StageStyle.DECORATED);
        primaryStage.setScene(scene);
        primaryStage.setWidth(1120);
        primaryStage.setHeight(700);
        width_stage = primaryStage.getWidth();

        spectrum_Pane = createSpectrum(anchorPane,primaryStage);
        AnchorPane.setBottomAnchor(spectrum_Pane,0.0);
        anchorPane.getChildren().addAll(imageView,spectrum_Pane,hBox);
        process(anchorPane);
//        initProcessBarView();
//        processSlider();
        play_bu.setOnAction((event -> {
            if(mediaPlayer !=null ) {
                if(buttonName.equals(ButtonEnum.PAUSE.getName()) && index == list.indexOf(mediaPlayer.getMedia())) {
                    mediaPlayer.setStartTime(currentSecond == null ? Duration.ZERO : currentSecond);
                    mediaPlayer.play();
                }else
                    playMusic(list,process);
            }else
                playMusic(list,process);
//                playMusic(list);
        }));

        slider.setOnMouseReleased((event -> {
            System.out.println(slider.getValue());
            mediaPlayer.setVolume(slider.getValue());
        }));

        pause_bu.setOnAction((event -> {
            currentSecond = mediaPlayer.getCurrentTime();
            process.setValue(currentSecond.toSeconds());
            buttonName = "pause";

            mediaPlayer.pause();

        }));


        //next song

        next_bu.setOnAction(event -> {
            buttonName = "next";
            playMusic(list,process);
            listView.getSelectionModel().select(index);
            listView.requestFocus();
        });
        //pre song
        pre_bu.setOnAction(event -> {
            buttonName = "pre";
            playMusic(list,process);
            listView.getSelectionModel().select(index);
            listView.requestFocus();
        });

        music_menu(songNameList,songs,list);
        primaryStage.show();
        VBox vBox = new VBox();
        wordText = new Text();
        wordText.setFont(Font.font(30));
        wordText.setFill(Paint.valueOf("#D1D1D1"));
        wordText.setLineSpacing(10);
        vBox.getChildren().add(wordText);
        vBox.setAlignment(Pos.CENTER);
//        AnchorPane.setRightAnchor(vBox,anchorPane.getPrefWidth()/2);
//        AnchorPane.setTopAnchor(vBox,anchorPane.getPrefHeight()/2);
        AnchorPane.setBottomAnchor(vBox,100.0);
        AnchorPane.setLeftAnchor(vBox,anchorPane.getWidth()*0.4);
//        vBox.setLayoutX(300);
//        vBox.setLayoutY(300);
        anchorPane.getChildren().add(vBox);

        songWordsMap = Utils.getSongWords();

    }

    /**
     *
     * @param list
     * @param process  silder
     */
    public void playMusic(List<Media> list,Slider process){
//        mediaPlayer = new MediaPlayer(list.get(0));
        if(mediaPlayer != null) {
            if(buttonName.equals(ButtonEnum.NEXT.getName()))
                index = list.indexOf(mediaPlayer.getMedia()) + 1;
            else if (buttonName.equals(ButtonEnum.PRE.getName()))
                index = list.indexOf((mediaPlayer.getMedia()))-1;
//            else
//                buttonName.equals(ButtonEnum.PLAY.getName())
            if (index == list.size())
                index = 0;
            else if(index == -1)
                index = list.size()-1;
            mediaPlayer.dispose();
        }
        System.out.println(index);
        mediaPlayer= new MediaPlayer(list.get(index));
        mediaPlayer.setOnReady(()->{
            System.out.println("准备完成");
            Duration totalDuration = mediaPlayer.getTotalDuration();
            process.setValue(0);
            process.setMax(totalDuration.toSeconds());
            mediaPlayer.setVolume(slider.getValue());
            /**
             * //TODO
             */
//            ObservableMap<String, Object> metadata = mediaPlayer.getMedia().getMetadata();
//            for( String  key : metadata.keySet()){
//                System.out.println(key +"---" +metadata.get(key));
//            }
        });
        mediaPlayer.play();
        mediaPlayer.currentTimeProperty().addListener(((observable, oldValue, newValue) -> {
            if (!mouse)
                process.setValue(newValue.toSeconds());
            if(songWordsMap.containsKey((int)newValue.toSeconds()))
                wordText.setText(songWordsMap.get((int) (newValue.toSeconds())));
            if(mediaPlayer.getTotalDuration().toSeconds()-newValue.toSeconds()<0.2 ){
                System.out.println("时间到了");
                index++;
                playMusic(list,process);
                listView.getSelectionModel().select(index);
            }

        }));

        mediaPlayer.setAudioSpectrumListener(((timestamp, duration, magnitudes, phases) -> {
//                     System.out.println(timestamp);
//                System.out.println(magnitudes.length+"---"+magnitudes[0]);
                    update_spectrum(magnitudes, spectrum_Pane);
//                anchorPane.getChildren().add(spectrum_Pane);
                }));
    }

    /**
     *
     * @param list
     * @param
     */
    public void playMusic(List<Media> list){
//        mediaPlayer = new MediaPlayer(list.get(0));
//        AnchorPane root = new AnchorPane();
//        root.setBackground(new Background(new BackgroundFill(Paint.valueOf())));
        if(mediaPlayer != null) {
            if(buttonName.equals(ButtonEnum.NEXT.getName()))
                index = list.indexOf(mediaPlayer.getMedia()) + 1;
            else if (buttonName.equals(ButtonEnum.PRE.getName()))
                index = list.indexOf((mediaPlayer.getMedia()))-1;
            if (index == list.size())
                index = 0;
            else if(index == -1)
                index = list.size()-1;
            mediaPlayer.dispose();
        }
        System.out.println(index);
        mediaPlayer= new MediaPlayer(list.get(index));
        mediaPlayer.setOnReady(()->{
            System.out.println("准备完成");
            Duration totalDuration = mediaPlayer.getTotalDuration();
            processRectangle.setHeight(totalDuration.toSeconds());
//            initProcessBarView();
            rectangle.setHeight(totalDuration.toSeconds());
//            processRectangle.setFill(Paint.valueOf(""));
//            processRectangle.setValue(0);
//            processRectangle.setMax(totalDuration.toSeconds());
            mediaPlayer.setVolume(slider.getValue());
            /**
             * //TODO
             */
//            ObservableMap<String, Object> metadata = mediaPlayer.getMedia().getMetadata();
//            for( String  key : metadata.keySet()){
//                System.out.println(key +"---" +metadata.get(key));
//            }

            mediaPlayer.play();
            mediaPlayer.currentTimeProperty().addListener(((observable, oldValue, newValue) -> {
                if (!mouse) {
                    //process.setValue(newValue.toSeconds());
                    processRectangle.setHeight(newValue.toSeconds());
                    processRectangle.setFill(Paint.valueOf("blue"));

                }

            }));

        });
        mediaPlayer.setAudioSpectrumListener(((timestamp, duration, magnitudes, phases) -> {
            // System.out.println(timestamp);
//                System.out.println(magnitudes.length+"---"+magnitudes[0]);
            update_spectrum(magnitudes,spectrum_Pane);
//                anchorPane.getChildren().add(spectrum_Pane);
        }));
    }

    /**
     * 更新频谱
     * @param magnitudes
     * @param spectrum_Pane
     */
    public void update_spectrum(float[] magnitudes,AnchorPane spectrum_Pane){
        int length = 100;
        for(int i=0;i<length;i++){
            Rectangle rectangle = (Rectangle)spectrum_Pane.getChildren().get(i);
//            System.out.println(anchorPane.getHeight());
            double an_height = anchorPane.getHeight()*0.6;
            //占0.4 height 的 百分之;
            double height = (magnitudes[i]+60)/60 * an_height;
            rectangle.setHeight(height);
//            System.out.println(height+"-----"+an_height*0.36);

            //矩形渐变填充
            List<Stop> stops = Arrays.asList(new Stop(0, Color.valueOf("#7D26CD"))
                    , new Stop(0.1, Color.valueOf("#1d8bcd")),new Stop(0.4, Color.valueOf("#9400D3")),new Stop(0.7, Color.valueOf("#CD69C9")),new Stop(1,Color.valueOf("#CD00CD")));
            LinearGradient linearGradient = new LinearGradient(0,0,width_stage/100*0.8,height,false,
                                    CycleMethod.NO_CYCLE, stops);
            rectangle.setFill(linearGradient);

            //这个是前版的单个格子一种填充的颜色，
//            if(height<(0.1*an_height)) {
//                rectangle.setFill(Paint.valueOf("#cc33cc"));
//            }else if(height>=(an_height*0.36))
//                rectangle.setFill(Paint.valueOf("#6666ff"));
//            else
//                rectangle.setFill(Paint.valueOf("#1d8bcd"));
        }
    }

    /**
     * 创建一个频谱pane，上面有100个rectangle
     * @param anchorPane
     * @return
     */
    public AnchorPane createSpectrum(AnchorPane anchorPane,Stage stage) {
        int length = 100;
        AnchorPane pan = new AnchorPane();
        double width = width_stage / 100 * 0.8;
        double y =0;
        for (int i = 0; i < length; i++) {
            Rectangle rectangle = new Rectangle();
            rectangle.setHeight(0);
            rectangle.setWidth(width);
            rectangle.setX(y);
            rectangle.setArcHeight(2);
            rectangle.setArcWidth(2);
//            rectangle.setStyle("-fx-background-color: aqua");
            AnchorPane.setBottomAnchor(rectangle, 0.0);
            pan.getChildren().add(rectangle);
            y = y+width+(width/4);
        }
        return pan;
    }

    /**
     * 进度条是以slider做的，
     * 缺点：没有显示已滑过的路径，不能给填充颜色
     */
    public void process(AnchorPane anchorPane){
        AnchorPane.setBottomAnchor(process,80.0);
        AnchorPane.setLeftAnchor(process,40.0);
        AnchorPane.setRightAnchor(process,40.0);
        process.valueProperty().addListener(((observable, oldValue, newValue) -> {
            currentSecond = Duration.seconds(newValue.doubleValue());
        }));
        process.setValueChanging(true);
        process.setOnMousePressed(event -> {
            System.out.println("press"+process.getValue());
            mouse = true;
        });
        process.setOnMouseReleased(event -> {
            System.out.println("release"+process.getValue());
            mediaPlayer.seek(Duration.seconds(process.getValue()));
            mouse = false;
        });
        anchorPane.getChildren().add(process);
    }


    /**
     *
     * @param
     */
    public void initProcessBarView(){
        rectangle.setWidth(10);
        rectangle.setArcWidth(10);
        rectangle.setArcHeight(10);
        rectangle.setRotate(90);
        rectangle.setFill(Color.valueOf("red"));
//        rectangle.setStroke(Color.valueOf("white"));
//        rectangle.setStrokeWidth(2);
        AnchorPane.setBottomAnchor(rectangle,80.0);
        AnchorPane.setLeftAnchor(rectangle,40.0);
        AnchorPane.setRightAnchor(rectangle,40.0);
//        anchorPane.getChildren().add(rectangle);
//        return rectangle;
    }

    public void processSlider(){
        processRectangle.setFill(Color.valueOf("red"));
        processRectangle.setWidth(8);
        processRectangle.setArcWidth(10);
        processRectangle.setArcHeight(10);
        processRectangle.setRotate(90);
        AnchorPane.setBottomAnchor(processRectangle,80.0);
        AnchorPane.setLeftAnchor(processRectangle,40.0);
        AnchorPane.setRightAnchor(processRectangle,40.0);
        anchorPane.getChildren().add(processRectangle);
        processRectangle.heightProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("processRectangle Height = "+newValue);
        });
    }

    public void loadMusicDir( String path,List<Media> list) throws FileNotFoundException, MalformedURLException, URISyntaxException {
        songNameList = new LoadSong().loadSong(path,list);
    }


    public void music_menu(List<String> songNamelist ,Button songs, List<Media> list) {

        StackPane stackPane = new StackPane();
//        stackPane.setPrefSize(500,500);
//        stackPane.prefWidthProperty().bind(anchorPane.widthProperty());
//        stackPane.prefHeightProperty().bind(anchorPane.heightProperty());
        stackPane.setScaleShape(true);
        anchorPane.heightProperty().addListener((observable, oldValue, newValue) -> {
            stackPane.setPrefHeight(newValue.doubleValue()*0.6);
        });
        anchorPane.widthProperty().addListener((observable, oldValue, newValue) -> {
            stackPane.setPrefWidth(newValue.doubleValue()*0.2);
            if(!isClicked)
                stackPane.setTranslateX(newValue.doubleValue());
            else
                stackPane.setTranslateX(newValue.doubleValue() - stackPane.getWidth());
        });
        double maxX = anchorPane.getBoundsInParent().getMaxX();
        System.out.println(maxX);
        stackPane.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
        //位移动画
        TranslateTransition translateTransition = new TranslateTransition();
        translateTransition.setNode(stackPane);
        translateTransition.setDuration(Duration.seconds(1));

        //fade 动画
        FadeTransition fadeTransition = new FadeTransition();
        fadeTransition.setNode(stackPane);
        fadeTransition.setDuration(Duration.seconds(1));

        //并行动画
        ParallelTransition parallelTransition = new ParallelTransition();
        parallelTransition.getChildren().addAll(translateTransition,fadeTransition);

        stackPane.setTranslateX(maxX);
        ObservableList<Text> observableList = FXCollections.observableArrayList();
        songNamelist.forEach((s -> {
            Text text = new Text(s);
            text.setFill(Paint.valueOf("#000000"));
            text.setFont(Font.font(20));
            observableList.add(text);
        }));
        listView = new ListView<>(observableList);
//        listView.setStyle("-fx-background-color: transparent");
        listView.setOpacity(0.6);
        songs.setOnAction(event -> {
            if (!isClicked) {
                translateTransition.setFromX(anchorPane.getWidth());
                translateTransition.setToX(anchorPane.getWidth() - stackPane.getWidth());
                fadeTransition.setFromValue(0);
                fadeTransition.setToValue(1);
            } else {
                translateTransition.setFromX(anchorPane.getWidth() - stackPane.getWidth());
                translateTransition.setToX(anchorPane.getWidth());
                fadeTransition.setFromValue(1);
                fadeTransition.setToValue(0);
            }
            isClicked = !isClicked;
            parallelTransition.play();
        });
        listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println(newValue);
        });
        listView.getSelectionModel().selectedIndexProperty().addListener(((observable, oldValue, newValue) -> {
            index = newValue.intValue();
            System.out.println(index);
        }));
        listView.setOnMouseClicked((event -> {
            if(event.getClickCount() == 2) {
                playMusic(list,process);
            }else
                buttonName = "play";
        }));
        listView.getSelectionModel().select(index);
        stackPane.getChildren().add(listView);
        anchorPane.getChildren().addAll(stackPane);
    }

    public static void main(String[] args){

        documentBase = new MusicPlayer().getHostServices().getDocumentBase().substring(5);
        path = documentBase+"music";
        URL resource = MusicPlayer.class.getResource(path);
        if(resource == null){
            File file = new File(path);
            file.mkdir();
        }
        URL image = MusicPlayer.class.getResource(documentBase+"/image");
        if(image == null){
            File file = new File(documentBase+"/image");
            file.mkdir();
        }
        launch(args);
    }

}
